﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Aspose.ExchangeSync.Data;
using Aspose.ExchangeSync.Components;
using Aspose.Email.Exchange;
using Aspose.Email.Mail;
using System.IO;
using System.Net;
using System.Net.Security;
using Aspose.Email.Outlook.Pst;
using Aspose.Email.Outlook;
using System.Web.Security;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Persistence;
using Umbraco.Core;
using Umbraco.Web;
using Umbraco.Core.Models.Membership;
using System.Linq;
using System.Collections;

namespace Aspose.ExchangeSync
{
    public partial class ExchangeSync : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }

        private bool ExchangeSettingsExist
        {
            get
            {
                Aspose_ExchangeSync_ServerDetails exchangeDetailsList = DatabaseHelper.CheckExchangeDetails(UmbracoAPIHelper.CurrentUserId);
                if (exchangeDetailsList != null)
                {
                    ViewState["ExchangeDetails"] = exchangeDetailsList;
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        private void ResetControls()
        {
            ExchangeToUmbracoSync.Visible = false;
            UmbracoToExchangeSync.Visible = false;
            ExchangeSettings.Visible = false;
        }

        protected void ExchangeToUmbracoHyperLink_Click(object sender, EventArgs e)
        {
            ResetControls();

            if (ExchangeSettingsExist)
            {
                ExchangeToUmbracoSyncResetControls();
                ExchangeToUmbracoSync.Visible = true;
            }
            else
            {
                ExchangeSettings.Visible = true;
                ExchangeToUmbracoClickedHiddenField.Value = "true";
            }
        }

        protected void UmbracoToExchangeHyperLink_Click(object sender, EventArgs e)
        {
            ResetControls();

            if (ExchangeSettingsExist)
            {
                UmbracoToExchangeSyncResetControls();
                UmbracoToExchangeSync.Visible = true;
            }
            else
            {
                ExchangeSettings.Visible = true;
                UmbracoToExchangeClickedHiddenField.Value = "true";
            }
        }

        protected void ExchangeSettingsHyperLink_Click(object sender, EventArgs e)
        {
            Aspose_ExchangeSync_ServerDetails exchangeDetailsList = DatabaseHelper.CheckExchangeDetails(UmbracoAPIHelper.CurrentUserId);
            if (exchangeDetailsList != null)
            {
                ServerURLTextBox.Text = exchangeDetailsList.ServerURL;
                UsernameTextBox.Text = exchangeDetailsList.Username;
                PasswordTextBox.Text = exchangeDetailsList.Password;
                DomainTextBox.Text = exchangeDetailsList.Domain;
            }

            ResetControls();
            ExchangeSettings.Visible = true;
        }

        protected void SaveButton_Click(object sender, EventArgs e)
        {
            ExchangeCredsErrorDiv.Visible = false;

            Aspose_ExchangeSync_ServerDetails serverDetails = new Aspose_ExchangeSync_ServerDetails();

            serverDetails.ServerURL = ServerURLTextBox.Text.Trim();
            serverDetails.Username = UsernameTextBox.Text.Trim();
            serverDetails.Password = PasswordTextBox.Text.Trim();
            serverDetails.Domain = DomainTextBox.Text.Trim();

            serverDetails.UserID = UmbracoAPIHelper.CurrentUserId;

            try
            {
                NetworkCredential credentials = new NetworkCredential(serverDetails.Username, serverDetails.Password, serverDetails.Domain);
                IEWSClient client = EWSClient.GetEWSClient(serverDetails.ServerURL, credentials);
            }
            catch (Exception)
            {
                ExchangeCredsErrorDiv.Visible = true;
                return;
            }

            serverDetails.Password = Crypto.Encrypt(serverDetails.Password);

            DatabaseHelper.AddUpdateServerDetails(serverDetails);

            ResetControls();

            if (ExchangeToUmbracoClickedHiddenField.Value.Equals("true"))
            {
                ExchangeToUmbracoSync.Visible = true;
                ExchangeToUmbracoClickedHiddenField.Value = "false";
            }
            else if (UmbracoToExchangeClickedHiddenField.Value.Equals("true"))
            {
                UmbracoToExchangeSync.Visible = true;
                UmbracoToExchangeClickedHiddenField.Value = "false";
            }
        }

        protected void CancelButton_Click(object sender, EventArgs e)
        {
            ResetControls();
        }

        #region Exchange To Umbraco

        public void ExchangeToUmbracoSyncResetControls()
        {
            ProcessSummaryDiv.Visible = ExchangeToUmbraco_MainDiv.Visible = NoRowSelectedErrorDiv.Visible = false;
            Into_Div.Visible = true;
        }

        protected void ExchangeToUmbracoSyncButton_Click(object sender, EventArgs e)
        {
            NoRowSelectedErrorDiv.Visible = false;

            if (ViewState["ExchangeDetails"] != null)
            {
                List<string> alreadyExistingList = new System.Collections.Generic.List<string>();

                List<string> contactsList = new List<string>();

                foreach (GridViewRow row in ExchangeContactsGridView.Rows)
                {
                    if (row.RowType == DataControlRowType.DataRow)
                    {
                        CheckBox chkRow = (row.Cells[0].FindControl("SelectedCheckBox") as CheckBox);
                        if (chkRow.Checked)
                        {
                            string email = ExchangeContactsGridView.DataKeys[row.RowIndex].Value.ToString();
                            contactsList.Add(email);
                        }
                    }
                }

                if (contactsList.Count() > 0)
                {
                    Aspose_ExchangeSync_ServerDetails serverDetails = (Aspose_ExchangeSync_ServerDetails)ViewState["ExchangeDetails"];

                    NetworkCredential credentials = new NetworkCredential(serverDetails.Username, serverDetails.Password, serverDetails.Domain);
                    IEWSClient client = EWSClient.GetEWSClient(serverDetails.ServerURL, credentials);

                    MapiContact[] contacts = client.ListContacts(client.MailboxInfo.ContactsUri);

                    if (UserRadioButton.Checked)
                    {
                        foreach (MapiContact contact in contacts)
                        {
                            if (contactsList.Contains(contact.ElectronicAddresses.Email1.EmailAddress))
                            {
                                IUser user = ApplicationContext.Current.Services.UserService.GetByEmail(contact.ElectronicAddresses.Email1.EmailAddress);

                                if (user == null)
                                    CreateUmbracoUser(contact);
                                else
                                    alreadyExistingList.Add(contact.ElectronicAddresses.Email1.EmailAddress);
                            }
                        }
                    }
                    else
                    {
                        foreach (MapiContact contact in contacts)
                         {
                             if (contactsList.Contains(contact.ElectronicAddresses.Email1.EmailAddress))
                             {
                                 IMember member = ApplicationContext.Current.Services.MemberService.GetByEmail(contact.ElectronicAddresses.Email1.EmailAddress);
                                 if (member == null)
                                     CreateUmbracoMember(contact);
                                 else
                                     alreadyExistingList.Add(contact.ElectronicAddresses.Email1.EmailAddress);
                             }
                         }
                    }
                }
                else
                {
                    NoRowSelectedErrorDiv.Visible = true;
                    return;
                }

                ImportedLiteral.Text = string.Format("{0} contact(s) have been imported to Umbraco successfully.", (contactsList.Count - alreadyExistingList.Count));

                if (alreadyExistingList.Count > 0)
                {
                    AlreadyExistingLiteral.Text = "The following contacts already exists in Umbraco and therefore not imported";
                    foreach (string email in alreadyExistingList)
                        AlreadyExistingLiteral.Text += "<br>" + email;
                }

                ProcessSummaryDiv.Visible = true;
                Into_Div.Visible = false;
                ExchangeToUmbraco_MainDiv.Visible = false;
            }
        }

        private void CreateUmbracoUser(MapiContact contact)
        {
            var userService = ApplicationContext.Current.Services.UserService;
            var userType = userService.GetUserTypeByAlias(UserTypesDropDownList.SelectedValue);
            string email = GetUserEmailAddress(contact);
            userService.CreateUserWithIdentity(email, email, userType);
        }

        private void CreateUmbracoMember(MapiContact contact)
        {
            var memberService = ApplicationContext.Current.Services.MemberService;
            string email = GetUserEmailAddress(contact);
            var member = memberService.CreateMemberWithIdentity(email, email, contact.NameInfo.DisplayName, MemberTypesDropDownList.SelectedItem.Text);
        }
        
        private string GetUserEmailAddress(MapiContact contact)
        {
            string emailAddress = string.Empty;

            emailAddress = contact.ElectronicAddresses.Email1.EmailAddress;
            if (!string.IsNullOrEmpty(emailAddress)) return emailAddress;

            emailAddress = contact.ElectronicAddresses.Email2.EmailAddress;
            if (!string.IsNullOrEmpty(emailAddress)) return emailAddress;

            emailAddress = contact.ElectronicAddresses.Email3.EmailAddress;
            if (!string.IsNullOrEmpty(emailAddress)) return emailAddress;

            return emailAddress;
        }

        private void RenderUserTypes()
        {
            var userService = ApplicationContext.Current.Services.UserService;
            UserTypesDropDownList.DataSource = userService.GetAllUserTypes();
            UserTypesDropDownList.DataBind();
        }

        private void RenderMemberTypes()
        {
            umbraco.cms.businesslogic.member.MemberType[] MemberTypes = umbraco.cms.businesslogic.member.MemberType.GetAll;
            MemberTypesDropDownList.DataSource = MemberTypes;
            MemberTypesDropDownList.DataBind();
        }

        protected void GetExchangeContactsButton_Click(object sender, EventArgs e)
        {
            Into_Div.Visible = false;
            ExchangeToUmbraco_MainDiv.Visible = true;

            RenderUserTypes();
            RenderMemberTypes();

            if (ViewState["ExchangeDetails"] != null)
            {
                Aspose_ExchangeSync_ServerDetails serverDetails = (Aspose_ExchangeSync_ServerDetails)ViewState["ExchangeDetails"];

                NetworkCredential credentials = new NetworkCredential(serverDetails.Username, serverDetails.Password, serverDetails.Domain);
                IEWSClient client = EWSClient.GetEWSClient(serverDetails.ServerURL, credentials);

                MapiContact[] contacts = client.ListContacts(client.MailboxInfo.ContactsUri);

                List<ExchangeContact> exchangeContactsList = new System.Collections.Generic.List<ExchangeContact>();

                foreach (MapiContact contact in contacts)
                {
                    exchangeContactsList.Add(new ExchangeContact(contact.NameInfo.DisplayName, contact.ElectronicAddresses.Email1.EmailAddress));
                }

                ExchangeContactsGridView.DataSource = exchangeContactsList;
                ExchangeContactsGridView.DataBind();
            }
        }

        #endregion Exchange To Umbraco

        #region Umbraco To Exchange

        public void UmbracoToExchangeSyncResetControls()
        {
            ProcessSummaryDiv.Visible = UmbracoToExchange_MainDiv.Visible = NoRowSelectedErrorDiv.Visible = false;
            Into_Div.Visible = true;
        }

        protected void UmbracoToExchangeSyncButton_Click(object sender, EventArgs e)
        {
            NoRowSelectedErrorDiv.Visible = false;

            if (ViewState["ExchangeDetails"] != null)
            {
                List<string> alreadyExistingList = new System.Collections.Generic.List<string>();
                
                if (UmbracoUsersGridView.Visible)
                {
                    List<IUser> selectedUsersList = new List<IUser>();

                    foreach (GridViewRow row in UmbracoUsersGridView.Rows)
                    {
                        if (row.RowType == DataControlRowType.DataRow)
                        {
                            CheckBox chkRow = (row.Cells[0].FindControl("SelectedCheckBox") as CheckBox);
                            if (chkRow.Checked)
                            {
                                string email = UmbracoUsersGridView.DataKeys[row.RowIndex].Value.ToString();
                                selectedUsersList.Add(ApplicationContext.Current.Services.UserService.GetByEmail(email));
                            }
                        }
                    }

                    if (selectedUsersList.Count > 0)
                    {
                        Aspose_ExchangeSync_ServerDetails serverDetails = (Aspose_ExchangeSync_ServerDetails)ViewState["ExchangeDetails"];
                        NetworkCredential credentials = new NetworkCredential(serverDetails.Username, serverDetails.Password, serverDetails.Domain);
                        IEWSClient client = EWSClient.GetEWSClient(serverDetails.ServerURL, credentials);

                        MapiContact[] contacts = client.ListContacts(client.MailboxInfo.ContactsUri);

                        foreach (IUser user in selectedUsersList)
                        {
                            if (contacts.FirstOrDefault(x => x.ElectronicAddresses.Email1.EmailAddress.Equals(user.Email)) == null)
                            {
                                MapiContact contact = BuildNewExchangeContact(user);
                                client.CreateContact(contact);
                            }
                            else
                            {
                                alreadyExistingList.Add(user.Email);
                            }
                        }
                    }
                    else
                    {
                        NoRowSelectedErrorDiv.Visible = true;
                        return;
                    }

                    UmbracoToExchange_ImportedLiteral.Text = string.Format("{0} contact(s) have been imported to Exchange Server successfully.", (selectedUsersList.Count - alreadyExistingList.Count));

                }
                else
                {
                    List<IMember> selectedUsersList = new List<IMember>();

                    foreach (GridViewRow row in UmbracoMembersGridView.Rows)
                    {
                        if (row.RowType == DataControlRowType.DataRow)
                        {
                            CheckBox chkRow = (row.Cells[0].FindControl("SelectedCheckBox") as CheckBox);
                            if (chkRow.Checked)
                            {
                                string email = UmbracoMembersGridView.DataKeys[row.RowIndex].Value.ToString();
                                selectedUsersList.Add(ApplicationContext.Current.Services.MemberService.GetByEmail(email));
                            }
                        }
                    }

                    if (selectedUsersList.Count > 0)
                    {
                        Aspose_ExchangeSync_ServerDetails serverDetails = (Aspose_ExchangeSync_ServerDetails)ViewState["ExchangeDetails"];

                        NetworkCredential credentials = new NetworkCredential(serverDetails.Username, serverDetails.Password, serverDetails.Domain);
                        IEWSClient client = EWSClient.GetEWSClient(serverDetails.ServerURL, credentials);
                        MapiContact[] contacts = client.ListContacts(client.MailboxInfo.ContactsUri);
                                                
                        foreach (IMember member in selectedUsersList)
                        {
                            if (contacts.FirstOrDefault(x => x.ElectronicAddresses.Email1.EmailAddress.Equals(member.Email)) == null)
                            {
                                MapiContact contact = BuildNewExchangeContactFromMember(member);
                                client.CreateContact(contact);
                            }
                            else
                            {
                                alreadyExistingList.Add(member.Email);
                            }
                        }

                    }
                    else
                    {
                        NoRowSelectedErrorDiv.Visible = true;
                        return;
                    }

                    UmbracoToExchange_ImportedLiteral.Text = string.Format("{0} contact(s) have been imported to Exchange Server successfully.", (selectedUsersList.Count - alreadyExistingList.Count));
                }
                
                if (alreadyExistingList.Count > 0)
                {
                    UmbracoToExchange_AlreadyExistingLiteral.Text = "The following contacts already exists in Exchange Server and therefore not imported";
                    foreach (string email in alreadyExistingList)
                        UmbracoToExchange_AlreadyExistingLiteral.Text += "<br>" + email;
                }

                UmbracoToExchange_ProcessSummaryDiv.Visible = true;
                Into_Div.Visible = false;
                UmbracoToExchange_MainDiv.Visible = false;
            }
        }

        private MapiContact BuildNewExchangeContact(IUser user)
        {
            MapiContact contact = new MapiContact();
            contact.ElectronicAddresses.Email1.EmailAddress = user.Email;
            contact.NameInfo.DisplayName = user.Name;
            return contact;
        }

        private MapiContact BuildNewExchangeContactFromMember(IMember user)
        {
            MapiContact contact = new MapiContact();
            contact.ElectronicAddresses.Email1.EmailAddress = user.Email;
            contact.NameInfo.DisplayName = user.Name;
            return contact;
        }

        protected void GetUmbracoUsersButton_Click(object sender, EventArgs e)
        {
            UmbracoMembersGridView.Visible = false;
            UmbracoUsersGridView.Visible = true;

            Into_Div.Visible = false;
            UmbracoToExchange_MainDiv.Visible = true;

            if (ViewState["ExchangeDetails"] != null)
            {
                var userService = ApplicationContext.Current.Services.UserService;
                int totalRecords = 0;
                UmbracoUsersGridView.DataSource = userService.GetAll(1, int.MaxValue, out totalRecords);
                UmbracoUsersGridView.DataBind();
            }
        }

        #endregion Umbraco To Exchange

        protected void GetUmbracoMembersButton_Click(object sender, EventArgs e)
        {
            UmbracoMembersGridView.Visible = true;
            UmbracoUsersGridView.Visible = false;

            Into_Div.Visible = false;
            UmbracoToExchange_MainDiv.Visible = true;

            if (ViewState["ExchangeDetails"] != null)
            {
                var memberService = ApplicationContext.Current.Services.MemberService;
                int totalRecords = 0;

                IEnumerable<IMember> listMembers = memberService.GetAll(1, int.MaxValue, out totalRecords);
                UmbracoMembersGridView.DataSource = listMembers;
                UmbracoMembersGridView.DataBind();
            }
        }
    }
}